package middleware

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"gitee.com/ysl729895/go-mall/internal/service"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
)

// AuthMiddleware 是一个 Gin 中间件，用于校验 JWT Token，保护需要登录的接口
// jwtKey: 用于验证 JWT 的密钥
// userRoleService/userPermService: 用于查询用户角色和权限
func AuthMiddleware(jwtKey []byte, userRoleService service.UserRoleService, rolePermService service.RolePermissionService) gin.HandlerFunc {
	return func(ctx *gin.Context) {
		tokenString := ctx.GetHeader("Authorization")
		fmt.Println(tokenString)
		// 检查 Authorization 头部是否存在且以 Bearer 开头
		if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer ") {
			ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    http.StatusUnauthorized,
				"message": "未授权，请先登录",
			})
			return
		}
		tokenString = strings.TrimPrefix(tokenString, "Bearer ")

		token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
			return jwtKey, nil
		})
		if err != nil || !token.Valid {
			ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    http.StatusUnauthorized,
				"message": "无效的Token",
			})
			return
		}

		// 解析 claims，将 user_id 写入上下文，便于后续 handler 使用
		if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
			if userID, exists := claims["user_id"]; exists {
				// 统一将 user_id 转为 uint 类型写入 ctx
				var uidUint uint
				switch v := userID.(type) {
				case float64:
					uidUint = uint(v)
				case int:
					uidUint = uint(v)
				case string:
					// 尝试解析字符串为 uint
					if parsed, err := strconv.ParseUint(v, 10, 64); err == nil {
						uidUint = uint(parsed)
					}
				}
				ctx.Set("user_id", uidUint)

				// 查询用户角色
				roles, _ := userRoleService.GetRolesByUserID(uidUint)
				var roleNames []string
				permSet := make(map[string]struct{})
				for _, role := range roles {
					roleNames = append(roleNames, role.Name)
					// 查询每个角色的权限
					perms, _ := rolePermService.GetPermissionsByRoleID(role.ID)
					for _, perm := range perms {
						permSet[perm.Name] = struct{}{}
					}
				}
				// 权限去重
				permNames := make([]string, 0, len(permSet))
				for k := range permSet {
					permNames = append(permNames, k)
				}
				ctx.Set("roles", roleNames)
				ctx.Set("permissions", permNames)
			}
		}
		ctx.Next()
	}
}
